module MODULE_DIV #(
	WIDTH = 64	
)(
	input								clk_i,
	input								rst_i,
	input	[WIDTH-1:0]		dividend_i,//被除数
	input	[WIDTH-1:0]		divisor_i,//除数
	input								div_valid_i,
	input								div_signed_i,
	output	[WIDTH-1:0]	quotient_o,
	output	[WIDTH-1:0]	remainder_o,
	output							result_valid_o
);	

wire [WIDTH-1:0]subresult;

//get abs of dividend and divisor
wire [WIDTH-1:0]	dividend_abs;
wire [WIDTH-1:0]	divisor_abs;
assign dividend_abs[WIDTH-1:0] = div_signed_i & dividend_i[WIDTH-1] ? (~dividend_i[WIDTH-1:0] + 1):dividend_i[WIDTH-1:0];
assign divisor_abs[WIDTH-1:0] = div_signed_i & divisor_i[WIDTH-1] ? (~divisor_i[WIDTH-1:0] + 1):divisor_i[WIDTH-1:0];


//reg for dividend divisor postive_or_negative and so on

wire [WIDTH-1:0]	divisor_ro;
//Reg #(WIDTH,0)	divisor_reg (clk_i,rst_i,divisor_i[WIDTH-1:0],divisor_ro[WIDTH-1:0],div_valid_i);
Reg #(WIDTH,0)	divisor_reg (clk_i,rst_i,divisor_abs[WIDTH-1:0],divisor_ro[WIDTH-1:0],div_valid_i);

wire 						dividend_postive_ro;
wire						divisor_postive_ro;
Reg	#(1,0) dividend_positive_r(clk_i,rst_i,~dividend_i[WIDTH-1]|(~div_signed_i),dividend_postive_ro,div_valid_i);
Reg	#(1,0) divisor_positive_r(clk_i,rst_i,~divisor_i[WIDTH-1]|(~div_signed_i),divisor_postive_ro,div_valid_i);

	//reg valid to control div
wire [WIDTH:0]	valid;
Reg #(1,0) valid_1_r(clk_i,rst_i,div_valid_i,valid[0],1);
genvar i;
generate
	for(i =1;i<WIDTH+1;i++)begin
Reg#(1,0) valid_r(clk_i,rst_i,valid[i-1],valid[i],1);
	end
endgenerate
Reg #(1,0) valid_o_r(clk_i,rst_i,valid[WIDTH],result_valid_o,1);
wire doing_div = div_valid_i | (|valid[WIDTH:0]);

	//reg for dividend,	 shift left 1bit every cycle,and sub dividend_ro if needed
wire [2*WIDTH-1:0] dividend_next;
wire [2*WIDTH-1:0] dividend_ro;
wire [2*WIDTH-1:0] dividend_next_final_cycle;
wire [2*WIDTH-1:0] dividend_next_normal;
assign dividend_next_normal[2*WIDTH-1:0] = ~subresult[WIDTH-1] ?	{subresult[WIDTH-2:0],dividend_ro[WIDTH-1:0],1'b0}: {dividend_ro[2*WIDTH-2:0],1'b0};
assign dividend_next_final_cycle[2*WIDTH-1:0] = ~subresult[WIDTH-1] ?	{subresult[WIDTH-1:0],dividend_ro[WIDTH-1:0]}: {dividend_ro[2*WIDTH-1:0]};
assign dividend_next = div_valid_i ? {{WIDTH{1'b0}},dividend_abs[WIDTH-1:0]} : 
				valid[WIDTH] ? dividend_next_final_cycle: dividend_next_normal;
Reg #(2*WIDTH,0) dividend_reg(clk_i,rst_i,dividend_next[2*WIDTH-1:0],dividend_ro[2*WIDTH-1:0],doing_div);
	//reg for quotient
wire	[WIDTH-1:0] quotient_next;
wire	[WIDTH-1:0] quotient_abs;
wire	quotient_new_bit;
assign subresult[WIDTH-1:0] = dividend_ro[2*WIDTH-1:WIDTH] - divisor_ro[WIDTH-1:0];
assign quotient_new_bit = ~subresult[WIDTH-1];
assign quotient_next[WIDTH-1:0] =div_valid_i? 0:{quotient_abs[WIDTH-2:0],quotient_new_bit};
Reg #(WIDTH,0)	quotient_reg(clk_i,rst_i,quotient_next[WIDTH-1:0],quotient_abs[WIDTH-1:0],doing_div);
	//remainder_o
wire	[WIDTH-1:0] remainder_abs;
assign remainder_abs[WIDTH-1:0] =dividend_ro[2*WIDTH-1:WIDTH];

//choose the result
wire [1:0] key = {dividend_postive_ro,divisor_postive_ro};
MuxKeyWithDefault #(4,2,WIDTH) quotient_o_mux(.out(quotient_o[WIDTH-1:0]),.key(key[1:0]),.default_out(0),.lut({
	2'b00, quotient_abs[WIDTH-1:0],	
	2'b01, ~quotient_abs[WIDTH-1:0]+1,
	2'b10, ~quotient_abs[WIDTH-1:0]+1,
	2'b11, quotient_abs[WIDTH-1:0]	
}));
MuxKeyWithDefault #(4,2,WIDTH) remainder_o_mux(.out(remainder_o[WIDTH-1:0]),.key(key[1:0]),.default_out(0),.lut({
	2'b00,~remainder_abs[WIDTH-1:0]+1,
	2'b01,~remainder_abs[WIDTH-1:0]+1,
	2'b10,remainder_abs[WIDTH-1:0],
	2'b11,remainder_abs[WIDTH-1:0]
}));
endmodule
